import traceback

import docker
from harbor_api import Harbor_API
import os

class DockerManager:
    def __init__(self):
        # 从环境变量获取docker_url，默认使用tcp模式
        docker_url = os.getenv('DOCKER_HOST', 'tcp://127.0.0.1:2375')
        self.client = docker.APIClient(base_url=docker_url)
        
    def build_port_url(self, host, port):
        """构建带端口的URL"""
        if port == "80":
            return host
        return f"{host}:{port}"

    def login_registry(self, host, port, username, password):
        """登录到Docker仓库"""
        registry_url = f"http://{self.build_port_url(host, port)}"
        return self.client.login(
            username=username,
            password=password,
            registry=registry_url
        )

    def sync_image(self, source_config, target_config, projects=None):
        """同步单个镜像
        source_config: 源仓库配置，包含 host, port, username, password
        target_config: 目标仓库配置，包含 host, port, username, password
        projects: 需要同步的项目数组，默认为None
        """
        try:
            # 登录目标仓库
            self.login_registry(
                target_config['host'],
                target_config['port'],
                target_config['username'],
                target_config['password']
            )

            # 初始化Harbor API
            harbor_api = Harbor_API(
                source_config['host'],
                source_config['port'],
                source_config['username'],
                source_config['password'],
                ignore80=True
            )

            # 获取所有制品
            artifacts = harbor_api.get_all_artifacts(projects)
            total_images = len(artifacts)
            print("Total images: ", total_images)
            processed_images = 0

            for image in artifacts:
                try:
                    # 构建源和目标镜像URL
                    source_url = self.build_port_url(source_config['host'], source_config['port'])
                    image_name = image[len(source_url):]
                    target_url = self.build_port_url(target_config['host'], target_config['port'])
                    target_image = f"{target_url}{image_name}"

                    print(f"\t{image} => {target_image}")

                    # 拉取镜像
                    output = self.client.pull(image)
                    print(f"Pull output: {output}")

                    # 标记镜像
                    images = self.client.images(name=image)
                    if not images:
                        raise Exception(f"Failed to find pulled image: {image}")

                    select_image = images[0]
                    repo, tag = target_image.split(":")
                    self.client.tag(
                        image=select_image["Id"],
                        repository=repo,
                        tag=tag
                    )

                    # 推送镜像
                    push_res = self.client.push(target_image)
                    print(f"Push result: {push_res}")

                    processed_images += 1
                    progress = (processed_images / total_images) * 100
                    print(f"Progress: {progress:.2f}%")

                except Exception as e:
                    print(f"Error processing image {image}: {str(e)}")
                    traceback.print_exc()
                    continue

            return True, "同步完成"

        except Exception as e:
            traceback.print_exc()
            return False, f"同步失败: {str(e)}"

def main():
    # 示例配置
    source_config = {
        "host": "192.168.100.10",
        "port": "80",
        "username": "admin",
        "password": "Harbor12345"
    }
    
    target_config = {
        "host": "192.168.100.11",
        "port": "80",
        "username": "admin",
        "password": "Harbor12345"
    }
    
    docker_manager = DockerManager()
    success, message = docker_manager.sync_image(source_config, target_config)
    print(message)

if __name__ == '__main__':
    main()